home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1997 May / PC Plus Super CD Issue 127 (May 1997).iso / handson / handson.exe / PIECRUST.BAS < prev    next >
Encoding:
BASIC Source File  |  1997-05-01  |  53.4 KB  |  2,413 lines

  1. '<->
  2. DEFINT A-Z
  3. DECLARE SUB ziDragging ()
  4. ' Return if mouse active and still dragging, or else exhausted
  5.  
  6. DECLARE SUB ziDrawBank (FromButton, ToButton)
  7. ' Draw a bank of buttons (using Bank array)
  8.  
  9. DECLARE SUB ziExhaust ()
  10. ' Return when no keystrokes and no mouse buttons
  11.  
  12. DECLARE SUB ziLoadFont (Font$)
  13. ' Load a specified font
  14.  
  15. DECLARE SUB ziLocateMCursor (XCoord, YCoord)
  16. ' Locate mouse cursor to a named point
  17.  
  18. DECLARE SUB ziMouseOnButton (FromButton, ToButton)
  19. ' Sets FoundButton
  20.  
  21. DECLARE SUB ziPublish (Printstring$, size, italic)
  22. ' Print a string at graphics cursor (advanced)
  23. '   Size   = magnitude (per 8 pixels)
  24. '   Italic = +1 to make italic
  25. '          = +2 to make overprint (no background)
  26.  
  27. DECLARE SUB ziPublishHere (row, col, Printstring$, size, italic)
  28. ' Print a string at the specified text position
  29.  
  30. DECLARE SUB ziRadio (Button, FromButton, ToButton)
  31. ' Set one button in a Bank, resetting the rest
  32.  
  33. DECLARE SUB ziReadField (Min, Max, Permitted$)
  34. ' Read a field at the current TCursor location
  35. '   Permitted$ contains:
  36. '     * - any characters
  37. '     . - allow one full-stop (as decimal)
  38. '     A - auto-enter (when filled)
  39. '     C - capitalise letters
  40. '     E - ESC allowed to finish (skip) field
  41. '     J - justify (especially for numeric)
  42. '     N - numerics
  43. '     P - password-type display
  44. '     S - space
  45. '     X - alphabetic
  46. '     Y - Y or N (upper or lower)
  47.  
  48. DECLARE SUB ziSetMCursorVis (Status)
  49. ' Set visibility of mouse cursor
  50. '   Status = 0 for OFF
  51. '            1 for ON
  52. '            2 for ENQUIRE (set MCursorVis)
  53. '           10 for TEMPORARILY OFF
  54. '           11 for RESTORED (set MCursorVis)
  55.  
  56. DECLARE SUB ziWander (Timeout!)
  57. ' Timeout  = in seconds (0 = none)
  58. ' Response =   0 = (0:00) timed out
  59. '              n = (0:n)  displacement into Allowed$
  60.  
  61. ' key           &h01xx  &h02xx  &h04xx  &h08xx  &h10xx  &h20xx  &h40xx
  62. '                plain   CTRL    shift   Mouse    Fn   CTRL-Fn  shift-Fn
  63.  
  64. ' Enter      0    *       *       -      double    -      -       -
  65. ' (left)     1    *       *       -      left     F1     ^F1     +F1
  66. ' (right)    2    *       *       -      right    F2     ^F2     +F2
  67. ' (up)       3    *       -       -      both     F3     ^F3     +F3
  68. ' (down)     4    *       -       -    leftdrag   F4     ^F4     +F4
  69.  
  70. ' Backspace  5    *       *       -    rightdrag  F5     ^F5     +F5
  71. ' Home       6    *       *       -    bothdrag   F6     ^F6     +F6
  72. ' End        7    *       *       -       -       F7     ^F7     +F7
  73.  
  74. ' PgUP       8    *       *       -       -       F8     ^F8     +F8
  75. ' PgDN       9    *       *       -       -       F9     ^F9     +F9
  76.  
  77. ' Tab       10    *       -       *       -       F10    ^F10    +F10
  78. ' Escape    11    *       -       -       -       F11    ^F11    +F11
  79. '           12    -       -       -       -       F12    ^F12    +F12
  80.  
  81. ' Allowed$  = other allowed strokes
  82. ' (Note:  DClick is a flag permitting Double-clicks of mouse - slower!)
  83.  
  84. DEFINT A-Z
  85. DECLARE SUB zsAlignGCursor ()
  86. ' Align graphic cursor to same as text cursor
  87. '  - sets Row, Col, GXloc, GYloc
  88.  
  89. DECLARE SUB zsAlignTCursor ()
  90. ' Align text cursor to same as graphic cursor
  91. '  - sets Row, Col, GXloc, GYloc
  92.  
  93. DECLARE SUB zsLocateGCursor (XCoord, YCoord)
  94. ' Locate graphic cursor to a named point
  95.  
  96. DECLARE SUB zsPastel (XCoord, YCoord, Wide, Deep, colour1, colour2)
  97. ' Colour the defined oblong with a pastel mix of two colours
  98. '  Deep = 0 or 1 - square
  99. '       = n      - Y-pixel depth
  100.  
  101. DECLARE SUB zsSetScrnMode (Mode, HiRows, HiCols)
  102. ' Mode = 9, 12 or 13
  103. ' HiRows = 1 to make high number of rows
  104. ' HiCols = 1 to make high number of cols (80)
  105. ' Set SCREEN parameters and blank the screen
  106. '  - sets ScrnMode, Xmax, Ymax, Rows, Cols, XYRatio!
  107. '  - uses FG and optionally BG (colours)
  108.  
  109. DECLARE SUB zsSubstitute (XCoord, YCoord, Wide, Deep, colour1, colour2)
  110. ' Substitute one colour with another within the defined oblong
  111. '  Deep = 0 or 1 - square
  112. '       = n      - Y-pixel depth
  113.  
  114. DECLARE SUB zzAlphaSort (Table$())
  115. ' Sort alphabetically the strings in the table; limited by " SortCount"
  116.  
  117. DECLARE SUB zzBasicInt (IntType)
  118. ' Execute interrupt (params in REGS.AX etc)
  119.  
  120. DECLARE SUB zzChangeDir (Directory$)
  121. ' Change to a particular directory
  122. '  -sets Directory$; eg "." will be changed to current directory
  123. ' if error occurs, Directory$ is returned as "?"
  124.  
  125. DECLARE SUB zzChangeDrive (Drive$)
  126. ' Change to a particular drive
  127. ' if Drive$ is empty on input, current drive is returned
  128. ' if error occurs, Drive$ is returned as "?"
  129.  
  130. DECLARE SUB zzCritOff ()
  131. ' turns off Critical Error Handling
  132.  
  133. DECLARE SUB zzCritOn ()
  134. ' restores normal Critical Error Handling
  135.  
  136. DECLARE SUB zzFileSelectBox (Pattern$)
  137. ' File Select Box function to choose an input file
  138.  
  139. DECLARE SUB zzInPath (Field$)
  140. ' Return full path to a file (in same string)
  141.  
  142. DECLARE SUB zzSearchD (Pattern$)
  143. ' Search for DIRECTORIES matching the pattern
  144. '  - sets Directories and Directories$()
  145.  
  146. DECLARE SUB zzSearchF (Pattern$)
  147. ' Search for FIILENAMES matching the pattern
  148. '  - sets FileNames and FileNames$()
  149.  
  150. DECLARE SUB zzValidate (Directory$)
  151. ' validate the named path and return its full
  152. '   (unqualified) name, including drive
  153. ' if error occcurs, Directory$ is returned as "?"
  154.  
  155. '================================================
  156. '/  UK copyright (c) 1997 by Future Publishing
  157. '/
  158. '/
  159. '/
  160. '/
  161. '================================================
  162. TYPE REGISTERS
  163.   AX AS INTEGER
  164.   BX AS INTEGER
  165.   CX AS INTEGER
  166.   DX AS INTEGER
  167.   DS AS INTEGER
  168.   SI AS INTEGER
  169.   ES AS INTEGER
  170.   DI AS INTEGER
  171.   FL AS INTEGER
  172. END TYPE
  173.  
  174. TYPE Buttons
  175.   Xloc AS INTEGER
  176.   Yloc AS INTEGER
  177.   Wide AS INTEGER
  178.   Deep AS INTEGER
  179. '  0 = checkbutton
  180. '  1 = square sculptured
  181. '  n = Y-pixels deep
  182.   State AS INTEGER
  183. '  0 = off
  184. '  1 = on
  185.   Active AS INTEGER
  186. '  0 = inactive
  187. '  1 = active
  188. END TYPE
  189.  
  190. CONST Pi! = 3.14159
  191. CONST Ex! = 2.71828
  192. CONST DegToRad! = .0174533
  193. CONST RadToDeg! = 57.2958
  194.  
  195. CONST ziNoShift = &H1
  196. CONST ziCTRL = &H2
  197. CONST ziShift = &H4
  198. CONST ziMouse = &H8
  199. CONST ziFn = &H10
  200. CONST ziCTRLFn = &H20
  201. CONST ziShiftFn = &H40
  202.  
  203. CONST ziL = 1
  204. CONST ziR = 2
  205. CONST ziUp = 3
  206. CONST ziDn = 4
  207. CONST ziBS = 5
  208. CONST ziHome = 6
  209. CONST ziEnd = 7
  210. CONST ziPgUp = 8
  211. CONST ziPgDn = 9
  212. CONST ziTab = 10
  213. CONST ziEsc = 11
  214.  
  215. CONST ziDbl = 0
  216. CONST ziBoth = 3
  217. CONST ziLDrag = 4
  218. CONST ziRDrag = 5
  219. CONST ziBothDrag = 6
  220.  
  221. DIM SHARED Regs AS REGISTERS
  222. DIM SHARED Bank(20) AS Buttons
  223. DIM SHARED Bad, Module$
  224. DIM SHARED Mouse, MCursorVis, MXloc, MYloc
  225. DIM SHARED DClick
  226. DIM SHARED ScrnMode, bg, fg, TCursor
  227. DIM SHARED Xmax, Ymax, GXloc, GYloc, XYratio!
  228. DIM SHARED Rows, Cols, row, col
  229. DIM SHARED Allowed$, Field$
  230. DIM SHARED FoundButton
  231. DIM SHARED Font(255, 7)
  232. DIM SHARED Response, HResponse, LResponse
  233. DIM SHARED SortCount
  234. REDIM SHARED Directories$(500)
  235. REDIM SHARED FileNames$(500)
  236. DIM SHARED Directories, FileNames
  237.  
  238. DIM SHARED IRET AS STRING * 3
  239. IRET = CHR$(&HB0) + CHR$(&H0) + CHR$(&HCF)
  240. DIM SHARED CritSeg, CritPtr, CritCount
  241.  
  242. '++++++++++++++++++++++++
  243. RANDOMIZE TIMER
  244. ON ERROR GOTO RESUMENEXT
  245. RESUMENEXT:
  246.   IF ERR = 255 THEN
  247.     CLS
  248.     BEEP
  249.     PRINT "Cannot find module "; Module$
  250.     SLEEP
  251.     SYSTEM
  252.   END IF
  253.   IF ERR THEN
  254.     Bad = ERR
  255.     RESUME NEXT
  256.   END IF
  257. Regs.AX = &H3524
  258. CALL zzBasicInt(&H21)
  259. CritSeg = Regs.ES
  260. CritPtr = Regs.BX
  261. '++++++++++++++++++++++++
  262. ' Test for presence of a mouse
  263. Mouse = 0
  264. Regs.AX = 0
  265. CALL zzBasicInt(&H33)
  266. IF Regs.AX THEN
  267.   Mouse = 1
  268.   CALL ziSetMCursorVis(0)
  269. END IF
  270. '++++++++++++++++++++++++
  271. ' Load the ASCII font
  272. CALL ziLoadFont("Ascii8x8")
  273. '/==================================/'
  274. '/  End of Standard Piecrust code   /'
  275. '/==================================/'
  276. '<+>
  277.  
  278. '<->
  279. '<p>
  280. '++++++++++++++++++++++++
  281. SUB ziDragging
  282.  
  283.   IF Mouse AND MCursorVis THEN
  284.     SELECT CASE Response
  285.     CASE 2052 TO 2054
  286.       Regs.AX = 3
  287.       CALL zzBasicInt(&H33)
  288.       IF Regs.BX = Response - 2051 THEN
  289.     EXIT SUB
  290.       END IF
  291.     END SELECT
  292.   END IF
  293.   CALL ziExhaust
  294.  
  295. END SUB
  296.  
  297. '<p>
  298. '++++++++++++++++++++++++
  299. SUB ziDrawBank (FromButton, ToButton)
  300.  
  301.   CALL ziSetMCursorVis(10)
  302.  
  303.   FOR i = FromButton TO ToButton
  304.  
  305.     IF Bank(i).Active THEN
  306.  
  307.       IF Bank(i).State THEN
  308.     colour1 = 8
  309.       ELSE
  310.     colour1 = 15
  311.       END IF
  312.       colour2 = colour1 XOR 7
  313.  
  314.       XCoord = Bank(i).Xloc
  315.       YCoord = Bank(i).Yloc
  316.       XWidth = Bank(i).Wide
  317.       YDepth = Bank(i).Deep
  318.       X2Coord = XCoord + XWidth
  319.  
  320.       IF YDepth THEN
  321.     IF YDepth = 1 THEN
  322.       Y2Coord = YCoord + XWidth / XYratio!
  323.     ELSE
  324.       Y2Coord = YCoord + YDepth
  325.     END IF
  326.     LINE (XCoord, YCoord)-(X2Coord - 1, YCoord), colour1
  327.     LINE (XCoord, YCoord)-(XCoord, Y2Coord - 1), colour1
  328.     LINE (XCoord + 1, Y2Coord)-(X2Coord, Y2Coord), colour2
  329.     LINE (X2Coord, YCoord)-(X2Coord, Y2Coord), colour2
  330.       ELSE
  331.     A = XWidth \ 2
  332.     B = A / XYratio!
  333.     C = XCoord + A
  334.     D = YCoord + B
  335.  
  336.     LINE (XCoord, YCoord)-(C + A, D + B), 7, BF
  337.  
  338.     CIRCLE (C, D), A, 8
  339.     CIRCLE (C, D), A - 1, 8
  340.     PAINT (C, D), 7, 7
  341.     IF Bank(i).State THEN
  342.       CIRCLE (C, D), XWidth \ 3, 8
  343.       PAINT (C, D), 8, 8
  344.     END IF
  345.       END IF
  346.     END IF
  347.  
  348.   NEXT
  349.  
  350.   CALL ziSetMCursorVis(11)
  351.  
  352. END SUB
  353.  
  354. '<p>
  355. '++++++++++++++++++++++++
  356. SUB ziExhaust
  357.  
  358.   DO
  359.     x$ = INKEY$
  360.   LOOP WHILE LEN(x$)
  361.  
  362.   IF Mouse AND MCursorVis THEN
  363.     DO
  364.       Regs.AX = 3
  365.       CALL zzBasicInt(&H33)
  366.     LOOP WHILE (Regs.BX AND 3)
  367.   END IF
  368.   Response = 0
  369. END SUB
  370.  
  371. '<p>
  372. '++++++++++++++++++++++++
  373. SUB ziLoadFont (Font$)
  374.  
  375.   DEF SEG = VARSEG(Font(0, 0))
  376.  
  377.   Module$ = Font$ + ".OVL"
  378.   CALL zzInPath(Module$)
  379.   IF Module$ = "" THEN
  380.     Module$ = Font$ + ".OVL"
  381.     ERROR 255
  382.   ELSE
  383.     BLOAD Module$, VARPTR(Font(0, 0))
  384.   END IF
  385.  
  386.   DEF SEG
  387.  
  388. END SUB
  389.  
  390. '<p>
  391. '++++++++++++++++++++++++
  392. SUB ziLocateMCursor (XCoord, YCoord)
  393.  
  394.   IF Mouse THEN
  395.     MXloc = XCoord
  396.     MYloc = YCoord
  397.     Regs.AX = 4
  398.     Regs.CX = XCoord
  399.     Regs.DX = YCoord
  400.     CALL zzBasicInt(&H33)
  401.     CALL ziSetMCursorVis(1)
  402.   END IF
  403.  
  404. END SUB
  405.  
  406. '<p>
  407. '++++++++++++++++++++++++
  408. SUB ziMouseOnButton (FromButton, ToButton)
  409.  
  410.   FoundButton = 0
  411.   FOR i = FromButton TO ToButton
  412.     IF Bank(i).Active THEN
  413.       IF Bank(i).Deep < 2 THEN
  414.     j = Bank(i).Wide / XYratio!
  415.       ELSE
  416.     j = Bank(i).Deep
  417.       END IF
  418.       IF MXloc > Bank(i).Xloc THEN
  419.     IF MXloc < Bank(i).Xloc + Bank(i).Wide THEN
  420.       IF MYloc > Bank(i).Yloc THEN
  421.         IF MYloc < Bank(i).Yloc + j THEN
  422.           FoundButton = i
  423.           EXIT SUB
  424.         END IF
  425.       END IF
  426.     END IF
  427.       END IF
  428.     ELSE
  429.       EXIT SUB
  430.     END IF
  431.   NEXT
  432.  
  433. END SUB
  434.  
  435. '<p>
  436. '++++++++++++++++++++++++
  437. SUB ziPublish (Printstring$, size, italic)
  438.  
  439.   CALL ziSetMCursorVis(10)
  440.  
  441.   xx = POINT(0)
  442.   yy = POINT(1)
  443.   IF size THEN
  444.     Scale = size
  445.   ELSE
  446.     Scale = 1
  447.   END IF
  448.  
  449.   LenString = LEN(Printstring$)
  450.  
  451.   ExpScale = 8 * Scale
  452.   limxx = xx + ExpScale * LenString - 1
  453.   limyy = yy + ExpScale - 1
  454.  
  455.   IF italic AND 1 THEN
  456.     limxx = limxx + 4 * Scale
  457.   END IF
  458.  
  459.  
  460.   IF italic AND 2 THEN
  461.   ELSE
  462.     LINE (xx, yy)-(limxx, limyy), bg, BF
  463.   END IF
  464.  
  465.  
  466.   FOR A = 0 TO LenString - 1
  467.     x = ASC(MID$(Printstring$, A + 1, 1))
  468.     B = xx + ExpScale * A
  469.     FOR y = 0 TO 7
  470.       C = Font(x, y)
  471.       D = y * Scale
  472.       e = yy + D
  473.       IF italic AND 1 THEN
  474.     F = B + 4 * Scale - (D + Scale - 1) \ 2 - 1
  475.       ELSE
  476.     F = B
  477.       END IF
  478.       g = 128
  479.       DO
  480.     IF C AND g THEN
  481.       FOR h = 0 TO Scale - 1
  482.         FOR i = 0 TO Scale - 1
  483.           PSET (F + h, e + i), fg
  484.         NEXT
  485.       NEXT
  486.     END IF
  487.     F = F + Scale
  488.     g = g \ 2
  489.       LOOP UNTIL g = 0
  490.     NEXT
  491.   NEXT
  492.   CALL zsLocateGCursor(limxx + 1, yy)
  493.  
  494.   CALL ziSetMCursorVis(11)
  495.  
  496. END SUB
  497.  
  498. SUB ziPublishHere (row, col, Printstring$, size, italic)
  499.  
  500.  IF row + col > 0 THEN
  501.   LOCATE row, col
  502.  END IF
  503.  CALL zsAlignGCursor
  504.  CALL ziPublish(Printstring$, size, italic)
  505.  CALL zsAlignTCursor
  506.  
  507. END SUB
  508.  
  509. '<p>
  510. '++++++++++++++++++++++++
  511. SUB ziRadio (Button, FromButton, ToButton)
  512.  
  513.   IF Button >= FromButton THEN
  514.     IF Button <= ToButton THEN
  515.       FOR A = FromButton TO ToButton
  516.     Bank(A).State = 0
  517.       NEXT
  518.     END IF
  519.   END IF
  520.  
  521.   Bank(Button).State = 1
  522.   CALL ziDrawBank(FromButton, ToButton)
  523.  
  524. END SUB
  525.  
  526. '<p>
  527. '++++++++++++++++++++++++
  528. SUB ziReadField (Min, Max, Permitted$)
  529.  
  530.   CALL ziSetMCursorVis(10)
  531.  
  532.   atRow = CSRLIN
  533.   atCol = POS(x)
  534.   Field$ = ""
  535.   PRINT CHR$(219); SPACE$(Max);
  536.   Rules$ = UCASE$(Permitted$)
  537.  
  538.   brake = 1
  539.   WHILE brake
  540.     x$ = ""
  541.     WHILE LEN(x$) = 0
  542.       x$ = INKEY$
  543.     WEND
  544.     IF INSTR(Rules$, "C") THEN x$ = UCASE$(x$)
  545.     oldLen = LEN(Field$)
  546.     Good = 0
  547.     IF INSTR(Rules$, ".") THEN
  548.       IF x$ = "." THEN
  549.     IF INSTR(Field$, ".") = 0 THEN
  550.       Good = 1
  551.     END IF
  552.       END IF
  553.     END IF
  554.     IF INSTR(Rules$, "N") THEN
  555.       IF INSTR("0123456789", x$) THEN
  556.     Good = 1
  557.       END IF
  558.     END IF
  559.     IF INSTR(Rules$, "S") THEN
  560.       IF x$ = " " THEN
  561.     Good = 1
  562.       END IF
  563.     END IF
  564.     IF INSTR(Rules$, "X") THEN
  565.       IF INSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ", UCASE$(x$)) THEN
  566.     Good = 1
  567.       END IF
  568.     END IF
  569.     IF INSTR(Rules$, "Y") THEN
  570.       IF INSTR("YyNy", x$) THEN
  571.     Good = 1
  572.       END IF
  573.     END IF
  574.     IF Good THEN
  575.       Field$ = Field$ + x$
  576.       IF INSTR(Field$, ".") THEN
  577.     NewMax = Max + 1
  578.       ELSE
  579.     NewMax = Max
  580.       END IF
  581.       Field$ = MID$(Field$, 1, NewMax)
  582.     END IF
  583.  
  584.     ' handle Bkspace
  585.     IF ASC(x$) = 8 AND LEN(Field$) THEN
  586.       Field$ = MID$(Field$, 1, LEN(Field$) - 1)
  587.     END IF
  588.  
  589.     Signif$ = Field$ + "X"
  590.     WHILE INSTR(" 0", MID$(Signif$, 1, 1))
  591.       Signif$ = MID$(Signif$, 2)
  592.     WEND
  593.     IF INSTR(Signif$, ".") THEN
  594.       SignifLen = LEN(Signif$) - 2
  595.     ELSE
  596.       SignifLen = LEN(Signif$) - 1
  597.     END IF
  598.  
  599.     ' handle Enter
  600.     IF ASC(x$) = 13 AND SignifLen >= Min THEN
  601.       oldLen = LEN(Field$) + 1
  602.       brake = 0
  603.     END IF
  604.  
  605.     ' handle Esc
  606.     IF ASC(x$) = 27 THEN
  607.       LOCATE atRow, atCol
  608.       PRINT CHR$(219); SPACE$(Max);
  609.       Field$ = ""
  610.       IF INSTR(Rules$, "E") THEN
  611.     EXIT SUB
  612.       END IF
  613.     END IF
  614.  
  615.     ' reprint if change, or beep if no change
  616.     IF oldLen = LEN(Field$) THEN
  617.       BEEP
  618.     ELSE
  619.       LOCATE atRow, atCol
  620.       IF INSTR(Rules$, "P") THEN
  621.     PRINT STRING$(LEN(Field$), 254); CHR$(219); " ";
  622.       ELSE
  623.     PRINT Field$; CHR$(219); " ";
  624.       END IF
  625.     END IF
  626.  
  627.     ' check for auto-Enter
  628.     IF INSTR(Rules$, "A") THEN
  629.       IF SignifLen = Max THEN
  630.     brake = 0
  631.       END IF
  632.     END IF
  633.   WEND
  634.  
  635.   ' justify if required
  636.   IF INSTR(Rules$, "J") THEN
  637.     WHILE MID$(Field$, 1, 1) = "0"
  638.       Field$ = MID$(Field$, 2)
  639.     WEND
  640.     Field$ = RIGHT$(SPACE$(NewMax) + Field$, NewMax)
  641.   END IF
  642.  
  643.   ' reprint, deleting the cursor
  644.   LOCATE atRow, atCol
  645.   IF INSTR(Rules$, "P") THEN
  646.     PRINT STRING$(LEN(Field$), 254); " ";
  647.   ELSE
  648.     PRINT Field$; " ";
  649.   END IF
  650.  
  651.   CALL ziSetMCursorVis(11)
  652.  
  653. END SUB
  654.  
  655. '<p>
  656. '++++++++++++++++++++++++
  657. SUB ziSetMCursorVis (Status) STATIC
  658.  
  659.   IF Mouse THEN
  660.     SELECT CASE Status
  661.     CASE 0
  662.       IF MCursorVis THEN
  663.        Regs.AX = 2
  664.        CALL zzBasicInt(&H33)
  665.       END IF
  666.     CASE 1
  667.       Regs.AX = 1
  668.       CALL zzBasicInt(&H33)
  669.     CASE 10
  670.       Regs.AX = &H2A
  671.       CALL zzBasicInt(&H33)
  672.       IF Regs.AX = 0 THEN
  673.     TempFlag = 1
  674.     Regs.AX = 2
  675.     CALL zzBasicInt(&H33)
  676.       ELSE
  677.     TempFlag = 0
  678.       END IF
  679.     CASE 11
  680.       IF TempFlag THEN
  681.     Regs.AX = 1
  682.     CALL zzBasicInt(&H33)
  683.       END IF
  684.     END SELECT
  685.     Regs.AX = &H2A
  686.     CALL zzBasicInt(&H33)
  687.     IF Regs.AX = 0 THEN
  688.       MCursorVis = 1
  689.     ELSE
  690.       MCursorVis = 0
  691.     END IF
  692.   END IF
  693. END SUB
  694.  
  695. '<p>
  696. '++++++++++++++++++++++++
  697. SUB ziWander (Timeout!)
  698.  
  699.   IF Timeout! = 0 THEN
  700.     WatchFor! = TIMER + 3600
  701.   ELSE
  702.     WatchFor! = TIMER + Timeout!
  703.   END IF
  704.  
  705.   Response = 0
  706.  
  707.   DO
  708.     x$ = INKEY$
  709.     IF LEN(x$) THEN
  710.       SELECT CASE LEN(x$)
  711.       CASE 1
  712.     A = INSTR(Allowed$, x$)
  713.     IF A THEN
  714.       Response = A
  715.       EXIT DO
  716.     END IF
  717.     SELECT CASE ASC(x$)
  718.     CASE 8: Response = 261
  719.     CASE 9: Response = 266
  720.     CASE 10: Response = 512
  721.     CASE 13: Response = 256
  722.     CASE 27: Response = 267
  723.     CASE 127: Response = 517
  724.     END SELECT
  725.     IF Response THEN
  726.       EXIT DO
  727.     END IF
  728.       CASE 2
  729.     Rightmost = ASC(RIGHT$(x$, 1))
  730.     SELECT CASE Rightmost
  731.     CASE 15: Response = 1019
  732.     CASE 59 TO 68
  733.       Response = 4038
  734.     CASE 72: Response = 187
  735.     CASE 71 TO 73
  736.       Response = 191
  737.     CASE 75: Response = 182
  738.     CASE 77: Response = 181
  739.     CASE 80: Response = 180
  740.     CASE 79 TO 81
  741.       Response = 184
  742.     CASE 84 TO 93
  743.       Response = 16301
  744.     CASE 94 TO 103
  745.       Response = 8099
  746.     CASE 115 TO 116
  747.       Response = 398
  748.     CASE 117: Response = 402
  749.     CASE 118: Response = 403
  750.     CASE 119: Response = 399
  751.     CASE 127: Response = 390
  752.     CASE 132: Response = 388
  753.     CASE 133 TO 134
  754.       Response = 3974
  755.     CASE 135 TO 136
  756.       Response = 16260
  757.     CASE 137 TO 138
  758.       Response = 8066
  759.     END SELECT
  760.     IF Response THEN
  761.       Response = Response + Rightmost
  762.       EXIT DO
  763.     END IF
  764.       END SELECT
  765.     END IF
  766.  
  767.     IF Mouse AND MCursorVis THEN
  768.       Regs.AX = 3
  769.       CALL zzBasicInt(&H33)
  770.       SELECT CASE Regs.BX
  771.       CASE 1 TO 3
  772.     Response = 2048 + Regs.BX
  773.     nowtime! = TIMER
  774.     DO
  775.       Regs.AX = 3
  776.       CALL zzBasicInt(&H33)
  777.       IF Regs.BX = 0 THEN EXIT DO
  778.     LOOP UNTIL TIMER - nowtime! > .3
  779.     IF Regs.BX = Response - 2048 THEN
  780.       Response = Response + 3
  781.     ELSE
  782.       IF Regs.BX = 0 AND Response = 2049 AND DClick THEN
  783.         nowtime! = TIMER
  784.         DO
  785.           Regs.AX = 3
  786.           CALL zzBasicInt(&H33)
  787.           IF Regs.BX = 1 THEN EXIT DO
  788.         LOOP UNTIL TIMER - nowtime! > .3
  789.         IF Regs.BX = 1 THEN
  790.           Response = 2048
  791.           CALL ziExhaust
  792.         END IF
  793.       END IF
  794.       IF Regs.BX = 3 THEN
  795.         Response = 2051
  796.       END IF
  797.     END IF
  798.       END SELECT
  799.       IF Response THEN
  800.     MXloc = Regs.CX
  801.     MYloc = Regs.DX
  802.     EXIT DO
  803.       END IF
  804.     END IF
  805.  
  806.   LOOP UNTIL WatchFor! < TIMER
  807.   HResponse = Response \ 256
  808.   LResponse = Response MOD 256
  809.  
  810. END SUB
  811.  
  812. '<p>
  813. '++++++++++++++++++++++++
  814. SUB zsAlignGCursor
  815.  
  816.   row = CSRLIN
  817.   col = POS(0)
  818.   GXloc = (col - 1) * ((Xmax + 1) \ Cols)
  819.   GYloc = (row - 1) * ((((Ymax + 1) \ Rows) * Rows + 1) \ Rows)
  820.   CALL zsLocateGCursor(GXloc, GYloc)
  821.  
  822. END SUB
  823.  
  824. '<p>
  825. '++++++++++++++++++++++++
  826. SUB zsAlignTCursor
  827.  
  828.   GXloc = POINT(0)
  829.   GYloc = POINT(1)
  830.   A = (Xmax + 1) / Cols
  831.   B = (Ymax + 1) / Rows
  832.   col = (GXloc + A - 1) \ A + 1
  833.   row = (GYloc + B - 1) \ B + 1
  834.   LOCATE row, col
  835.   CALL zsAlignGCursor
  836.  
  837. END SUB
  838.  
  839. '<p>
  840. '++++++++++++++++++++++++
  841. SUB zsLocateGCursor (XCoord, YCoord)
  842.  
  843.   GXloc = XCoord
  844.   GYloc = YCoord
  845.   PSET (GXloc, GYloc), POINT(GXloc, GYloc)
  846.  
  847. END SUB
  848.  
  849. '<p>
  850. '++++++++++++++++++++++++
  851. SUB zsPastel (XCoord, YCoord, Wide, Deep, colour1, colour2)
  852.  
  853.   CALL ziSetMCursorVis(10)
  854.  
  855.   IF Deep < 2 THEN
  856.     A = Wide / XYratio!
  857.   ELSE
  858.     A = Deep
  859.   END IF
  860.  
  861.   LINE (XCoord, YCoord)-(XCoord + Wide - 1, YCoord + A - 1), colour1, BF
  862.   FOR B = XCoord TO XCoord + Wide - 1 STEP 2
  863.     LINE (B, YCoord)-(B, YCoord + A - 1), colour2, , &H5555
  864.   NEXT
  865.   FOR B = XCoord + 1 TO XCoord + Wide - 1 STEP 2
  866.     LINE (B, YCoord)-(B, YCoord + A - 1), colour2, , &HAAAA
  867.   NEXT
  868.  
  869.   CALL ziSetMCursorVis(11)
  870.  
  871. END SUB
  872.  
  873. '<p>
  874. '++++++++++++++++++++++++
  875. SUB zsSetScrnMode (Mode, HiRows, HiCols)
  876.  
  877.   CALL ziSetMCursorVis(10)
  878.  
  879.   ScrnMode = Mode
  880.   SELECT CASE Mode
  881.   CASE 9
  882.     SCREEN 9
  883.     IF HiRows THEN
  884.       Rows = 43
  885.     ELSE
  886.       Rows = 25
  887.     END IF
  888.     Xmax = 639
  889.     Ymax = 349
  890.   CASE 12
  891.     SCREEN 12
  892.     IF HiRows THEN
  893.       Rows = 60
  894.     ELSE
  895.       Rows = 30
  896.     END IF
  897.     Xmax = 639
  898.     Ymax = 479
  899.   CASE 13
  900.     SCREEN 13
  901.     Rows = 25
  902.     Cols = 40
  903.     Xmax = 319
  904.     Ymax = 199
  905.   CASE ELSE
  906.     RETURN
  907.   END SELECT
  908.  
  909.   IF Mode <> 13 THEN
  910.     IF HiCols THEN
  911.       Cols = 80
  912.     ELSE
  913.       Cols = 40
  914.     END IF
  915.   END IF
  916.   WIDTH Cols, Rows
  917.   CLS
  918.   SELECT CASE Mode
  919.   CASE 9
  920.     COLOR fg, 0
  921.   CASE ELSE
  922.     COLOR fg
  923.   END SELECT
  924.  
  925.   LINE (0, 0)-(Xmax, Ymax), bg, BF
  926.   LOCATE 1, 1, 0
  927.   PSET (0, 0), bg
  928.   XYratio! = .75 * (Xmax + 1) / (Ymax + 1)
  929.  
  930.   CALL ziSetMCursorVis(11)
  931.  
  932. END SUB
  933.  
  934. '<p>
  935. '++++++++++++++++++++++++
  936. SUB zsSubstitute (XCoord, YCoord, Wide, Deep, colour1, colour2)
  937.  
  938.   CALL ziSetMCursorVis(10)
  939.  
  940.   IF Deep < 2 THEN
  941.     A = Wide / XYratio!
  942.   ELSE
  943.     A = Deep
  944.   END IF
  945.   FOR B = XCoord TO XCoord + Wide - 1
  946.     FOR C = YCoord TO YCoord + A - 1
  947.       IF POINT(B, C) = colour1 THEN
  948.     PSET (B, C), colour2
  949.       END IF
  950.     NEXT
  951.   NEXT
  952.  
  953.   CALL ziSetMCursorVis(11)
  954.  
  955. END SUB
  956.  
  957. '<p>
  958. '++++++++++++++++++++++++
  959. SUB zzAlphaSort (SortData$())
  960.  
  961.  DIM SortPointers(SortCount, 2)
  962.  
  963.  FOR i = 2 TO SortCount
  964.   j = 1
  965.  
  966.   DO
  967.    k = j
  968.    IF SortData$(i) < SortData$(j) THEN
  969.     j = SortPointers(j, 1)
  970.    ELSE
  971.     j = SortPointers(j, 2)
  972.    END IF
  973.   LOOP WHILE j <> 0
  974.  
  975.   IF SortData$(i) < SortData$(k) THEN
  976.    SortPointers(k, 1) = i
  977.   ELSE
  978.    SortPointers(k, 2) = i
  979.   END IF
  980.  NEXT
  981.  
  982.  SortPointers(0, 1) = 1
  983.  
  984.  
  985.  FOR i = 1 TO SortCount
  986.   j = 0
  987.   DO WHILE SortPointers(j, 1) <> 0
  988.    k = j
  989.    j = SortPointers(j, 1)
  990.   LOOP
  991.   SortPointers(k, 1) = SortPointers(j, 2)
  992.  
  993.   SWAP SortData$(i), SortData$(j)
  994.   SWAP SortPointers(i, 1), SortPointers(j, 1)
  995.   SWAP SortPointers(i, 2), SortPointers(j, 2)
  996.  
  997.   FOR k = 0 TO SortCount
  998.    FOR l = 1 TO 2
  999.     IF SortPointers(k, l) = i THEN SortPointers(k, l) = j
  1000.    NEXT
  1001.   NEXT
  1002.  NEXT
  1003.  
  1004. END SUB
  1005.  
  1006. '<p>
  1007. '++++++++++++++++++++++++
  1008. SUB zzBasicInt (IntType) STATIC
  1009.  
  1010.   DIM ASM(54)
  1011.   DEF SEG = VARSEG(ASM(0))
  1012.  
  1013.   IF ASM(1) = 0 THEN
  1014.     Module$ = "BASICINT.OVL"
  1015.     CALL zzInPath(Module$)
  1016.     IF Module$ = "" THEN
  1017.       Module$ = "BASICINT.OVL"
  1018.       ERROR 255
  1019.     ELSE
  1020.       BLOAD Module$, VARPTR(ASM(0))
  1021.     END IF
  1022.   END IF
  1023.  
  1024.   CALL ABSOLUTE(Regs, IntType, VARPTR(ASM(0)))
  1025.  
  1026.   DEF SEG
  1027.  
  1028. END SUB
  1029.  
  1030. '<p>
  1031. '++++++++++++++++++++++++
  1032. SUB zzChangeDir (Directory$)
  1033.  DIM str AS STRING * 65
  1034.  
  1035.  str = LTRIM$(RTRIM$(UCASE$(Directory$))) + CHR$(0)
  1036.  IF MID$(str, 2, 1) = ":" THEN
  1037.   curdrive$ = MID$(str, 1, 1)
  1038.   str = MID$(str, 3)
  1039.  ELSE
  1040.   Regs.AX = &H1900
  1041.   CALL zzBasicInt(&H21)
  1042.   curdrive$ = CHR$(65 + (Regs.AX AND 255))
  1043.  END IF
  1044.  IF MID$(str, 1, 1) = CHR$(0) THEN
  1045.   GOSUB zzChangeDirAA
  1046.   EXIT SUB
  1047.  END IF
  1048.  str = curdrive$ + ":" + str
  1049.  Regs.AX = &H3B00
  1050.  Regs.DS = VARSEG(str)
  1051.  Regs.DX = VARPTR(str)
  1052.  CALL zzBasicInt(&H21)
  1053.  IF (Regs.FL AND 256) = 256 THEN
  1054.   Directory$ = ""
  1055.  ELSE
  1056.   GOSUB zzChangeDirAA
  1057.  END IF
  1058.  EXIT SUB
  1059.  
  1060. zzChangeDirAA:
  1061.   Regs.AX = &H4700
  1062.   Regs.DX = ASC(curdrive$) - 64
  1063.   Regs.DS = VARSEG(str)
  1064.   Regs.SI = VARPTR(str)
  1065.   CALL zzBasicInt(&H21)
  1066.   i = INSTR(str, CHR$(0))
  1067.   Directory$ = curdrive$ + ":\" + MID$(str, 1, i - 1)
  1068.   RETURN
  1069. END SUB
  1070.  
  1071. '<p>
  1072. '++++++++++++++++++++++++
  1073. SUB zzChangeDrive (Drive$)
  1074.  
  1075.  CALL zzCritOff
  1076.  GOSUB zzChangeDriveProcess
  1077.  CALL zzCritOn
  1078.  
  1079.  EXIT SUB
  1080.  
  1081. zzChangeDriveProcess:
  1082.  
  1083.  Drive$ = LTRIM$(RTRIM$(UCASE$(Drive$)))
  1084.  IF LEN(Drive$) = 0 THEN
  1085.   Regs.AX = &H1900
  1086.   CALL zzBasicInt(&H21)
  1087.   Drive$ = CHR$(65 + (Regs.AX AND 255)) + ":"
  1088.   RETURN
  1089.  END IF
  1090.  
  1091.  IF LEN(Drive$) = 1 THEN Drive$ = Drive$ + ":"
  1092.  IF LEN(Drive$) > 2 THEN Drive$ = "?"
  1093.  
  1094.  IF MID$(Drive$, 2, 1) = ":" THEN
  1095.   drv = ASC(Drive$)
  1096.   Drive$ = "?"
  1097.   IF drv < 65 THEN RETURN
  1098.   IF drv > 90 THEN RETURN
  1099.   drv = drv - 65
  1100.  
  1101. ' establish whether this is a shared drive
  1102.  
  1103.   Regs.AX = &H440E
  1104.   Regs.BX = drv + 1
  1105.   CALL zzBasicInt(&H21)
  1106.   IF (Regs.FL AND 256) = 256 THEN
  1107.    Regs.AX = 0
  1108.   END IF
  1109.   Regs.AX = Regs.AX AND 255
  1110.   IF Regs.AX <> 0 THEN
  1111.    IF Regs.AX <> drv + 1 THEN
  1112.     drv = Regs.AX - 1
  1113.    END IF
  1114.   END IF
  1115.  
  1116. ' establish whether this is a valid drive
  1117.  
  1118.   Regs.AX = &H1C00
  1119.   Regs.DX = drv + 1
  1120.   CALL zzBasicInt(&H21)
  1121.   IF (Regs.AX AND 255) = 255 THEN RETURN
  1122.  
  1123. ' now change to it
  1124.  
  1125.   Regs.AX = &HE00
  1126.   Regs.DX = drv
  1127.   CALL zzBasicInt(&H21)
  1128.  
  1129.   Drive$ = CHR$(65 + drv) + ":"
  1130.  
  1131.  
  1132.  ELSE
  1133.   Drive$ = "?"
  1134.  END IF
  1135.  RETURN
  1136.  
  1137. END SUB
  1138.  
  1139. SUB zzCritOff
  1140.  
  1141.  Regs.AX = &H2524
  1142.  Regs.DS = VARSEG(IRET)
  1143.  Regs.DX = VARPTR(IRET)
  1144.  CALL zzBasicInt(&H21)
  1145.  CritCount = CritCount + 1
  1146.  
  1147. END SUB
  1148.  
  1149. SUB zzCritOn
  1150.  
  1151.  CritCount = CritCount - 1
  1152.  IF CritCount = 0 THEN
  1153.   Regs.AX = &H2524
  1154.   Regs.DS = CritSeg
  1155.   Regs.DX = CritPtr
  1156.   CALL zzBasicInt(&H21)
  1157.  END IF
  1158.  
  1159. END SUB
  1160.  
  1161. '<p>
  1162. '++++++++++++++++++++++++
  1163. SUB zzFileSelectBox (Pattern$)
  1164.  
  1165. DIM Devices(26)  ';valid devices have a non-zero value
  1166. DIM validDevs(27)
  1167.  
  1168. DIM parts$(11) ';ten deep is allowed
  1169. DIM Dirs$(200) ';lots of subdirectories
  1170. DIM Files$(200) ';lots of files
  1171. DIM str AS STRING * 65
  1172.  
  1173.  CALL zzCritOff
  1174.  GOSUB zzFileSelectBoxProcess
  1175.  CALL zzCritOn
  1176.  
  1177.  EXIT SUB
  1178.  
  1179. zzFileSelectBoxProcess:
  1180.  
  1181. ' create the screen
  1182.  
  1183.   IF screendone = 0 THEN
  1184.    bg = 7: fg = 15
  1185.    CALL zsSetScrnMode(9, 1, 1)
  1186.    fg = 0
  1187.    CALL ziPublishHere(3, 34, "Select a File", 1, 3)
  1188.    Stuff$ = "(Please Wait)"
  1189.    fg = 14
  1190.    GOSUB zzFileSelectBoxDD
  1191.  
  1192. ' print the headers
  1193.  
  1194.    fg = 8
  1195.    CALL ziPublishHere(42, 17, "Use left & right arrow keys to change columns", 0, 1)
  1196.   END IF
  1197.   screendone = 1
  1198.  
  1199.   fg = 8: CALL ziPublishHere(8, 2, "Drives", 2, 1): fg = 0
  1200.   LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1201.  
  1202.  
  1203.   IF NoDriveSelection = 0 THEN
  1204.    dev = 0: GOSUB zzFileSelectBoxAA
  1205.  
  1206. ' find the DTA
  1207.  
  1208.    Regs.AX = &H2F00
  1209.    CALL zzBasicInt(&H21)
  1210.    DTAseg = Regs.ES
  1211.    DTAptr = Regs.BX
  1212.  
  1213. ' establish the existing devices
  1214.  
  1215.    MaxDevs = 0
  1216.    FOR i = 1 TO 26
  1217.     Devices(i) = 0
  1218.     validDevs(i) = 0
  1219.     Regs.AX = &H440E
  1220.     Regs.BX = i
  1221.     CALL zzBasicInt(&H21)
  1222.     IF (Regs.FL AND 256) = 256 THEN
  1223.      Regs.AX = 0
  1224.     END IF
  1225.     Regs.AX = Regs.AX AND 255
  1226.     IF (Regs.AX = 0) OR (Regs.AX = i) THEN
  1227.      Regs.AX = &H1C00
  1228.      Regs.DX = i
  1229.      CALL zzBasicInt(&H21)
  1230.      IF (Regs.AX AND 255) <> 255 THEN
  1231.       MaxDevs = MaxDevs + 1
  1232.       Devices(i) = MaxDevs '; set the crossreference
  1233.       validDevs(MaxDevs) = i
  1234.      END IF
  1235.     END IF
  1236.    NEXT
  1237.  
  1238. ' print the valid drives as a list
  1239.  
  1240.    fg = 0
  1241.    FOR i = 1 TO MaxDevs
  1242.     x$ = CHR$(64 + validDevs(i)) + ":"
  1243.     CALL ziPublishHere(10 + i + i, 7, x$, 1, 0)
  1244.    NEXT
  1245.   END IF
  1246.   LINE (GXloc - 16, GYloc + 8)-(GXloc, 319), 7, BF 'clear rest of list
  1247.  
  1248.  
  1249.   NoDriveSelection = 0
  1250.  
  1251.   fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1252.   LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1253.  
  1254. ' carve off any 'wildcard' from the specified input parameter
  1255.  
  1256.   Pattern$ = UCASE$(LTRIM$(RTRIM$(Pattern$)))
  1257.   str = Pattern$
  1258.   IF INSTR(str, "?") + INSTR(str, "*") = 0 THEN
  1259.    base$ = Pattern$
  1260.    wild$ = "*.*"
  1261.   ELSE
  1262.    IF MID$(str, 2, 1) = ":" THEN
  1263.     start = 3
  1264.    ELSE
  1265.     start = 1
  1266.    END IF
  1267.    DO
  1268.     i = INSTR(start, str, "\")
  1269.     IF i <> 0 THEN
  1270.      start = i + 1
  1271.     END IF
  1272.    LOOP UNTIL i = 0
  1273.    base$ = MID$(str, 1, start - 1)
  1274.    wild$ = MID$(RTRIM$(str), start)
  1275.   END IF
  1276.  
  1277.   CALL zzValidate(base$)
  1278.   IF base$ = "?" THEN
  1279.    base$ = ""
  1280.    CALL zzChangeDir(base$)
  1281.   END IF
  1282.  
  1283.  
  1284.   IF MID$(base$, LEN(base$)) = "\" THEN
  1285.    basex$ = MID$(base$, 1, LEN(base$) - 1)
  1286.   ELSE
  1287.    basex$ = base$
  1288.   END IF
  1289.  
  1290.  
  1291.  
  1292. ' validate the "wildcard" portion
  1293.  
  1294. ' (make sure no more than one ".")
  1295.  
  1296.   i = INSTR(wild$, ".")
  1297.   IF i <> 0 THEN
  1298.    x$ = wild$
  1299.    MID$(x$, i, 1) = "+"
  1300.    IF INSTR(x$, ".") THEN
  1301.     wild$ = "*.*"
  1302.     i = 2
  1303.    END IF
  1304.   END IF
  1305.  
  1306. ' (divide it into its two component parts)
  1307.  
  1308.   IF i < 2 THEN
  1309.    wildl$ = wild$
  1310.    wildr$ = ""
  1311.   ELSE
  1312.    wildl$ = MID$(wild$, 1, i - 1)
  1313.    wildr$ = MID$(wild$, i + 1)
  1314.   END IF
  1315.   IF LEN(wildl$) > 8 OR LEN(wildr$) > 3 THEN
  1316.    wild$ = "*.*"
  1317.    wildl$ = "*"
  1318.    wildr$ = "*"
  1319.   END IF
  1320.  
  1321. ' (make sure no more than one TRAILING "*" in left part)
  1322.  
  1323.   i = INSTR(wildl$, "*")
  1324.   IF i <> 0 THEN
  1325.    IF i <> LEN(wildl$) THEN
  1326.     wild$ = "*.*"
  1327.     wildl$ = "*"
  1328.     wildr$ = "*"
  1329.    END IF
  1330.   END IF
  1331.  
  1332. ' (make sure no more than one TRAILING "*" in right part)
  1333.  
  1334.   i = INSTR(wildr$, "*")
  1335.   IF i <> 0 THEN
  1336.    IF i <> LEN(wildr$) THEN
  1337.     wild$ = "*.*"
  1338.     wildl$ = "*"
  1339.     wildr$ = "*"
  1340.    END IF
  1341.   END IF
  1342.  
  1343.   i = 39 - LEN(wild$) \ 2
  1344.   x$ = "[" + wild$ + "]"
  1345.   CALL ziPublishHere(7, i, x$, 0, 0)
  1346.  
  1347. ' determine the specified drive
  1348.  
  1349.   dev = Devices(ASC(base$) - 64)
  1350.   GOSUB zzFileSelectBoxAA
  1351.  
  1352. ' create the tree
  1353.  
  1354.   FOR i = 0 TO 11
  1355.    parts$(i) = ""
  1356.   NEXT
  1357.   x$ = basex$ + "\"
  1358.  
  1359.   levels = 0
  1360.   DO
  1361.    i = INSTR(x$, "\")
  1362.    IF i <> 0 THEN
  1363.     parts$(levels) = MID$(x$, 1, i - 1)
  1364.     levels = levels + 1
  1365.     x$ = MID$(x$, i + 1)
  1366.    END IF
  1367.   LOOP UNTIL i = 0
  1368.   parts$(0) = parts$(0) + "\"
  1369.   levels = levels - 1
  1370.  
  1371.   CALL ziPublishHere(12, 15, parts$(0), 0, 0)
  1372.  
  1373.   IF levels > 0 THEN
  1374.    FOR i = 1 TO levels
  1375.     x$ = SPACE$(i + i) + CHR$(179)
  1376.     CALL ziPublishHere(11 + i + i, 13, x$, 0, 0)
  1377.     x$ = SPACE$(i + i) + CHR$(192) + CHR$(196) + parts$(i)
  1378.     CALL ziPublishHere(12 + i + i, 13, x$, 0, 0)
  1379.    NEXT
  1380.   END IF
  1381.  
  1382.   oldtree = 255
  1383.   tree = levels
  1384.   GOSUB zzFileSelectBoxHH
  1385.  
  1386.  
  1387. ' test for subdirectories present
  1388.  
  1389.   olddline = 0
  1390.   x$ = basex$ + "\*.*"
  1391.   CALL zzSearchD(x$)
  1392.  
  1393.   IF Directories <> 0 THEN
  1394.    fg = 8: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1395.    FromDir = 1
  1396.    GOSUB zzFileSelectBoxEE
  1397.   END IF
  1398.  
  1399. ' test for files present
  1400.  
  1401.   x$ = basex$ + "\" + wild$
  1402.   CALL zzSearchF(x$)
  1403.  
  1404.   IF FileNames <> 0 THEN
  1405.    fg = 8: CALL ziPublishHere(8, 51, "Files", 2, 1): fg = 0
  1406.    FromFile = 1
  1407.    GOSUB zzFileSelectBoxFF
  1408.   END IF
  1409.  
  1410. ' determine where to start
  1411.  
  1412.   IF FileNames = 0 THEN
  1413.    IF Directories = 0 THEN
  1414.     fg = 4: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1415.     Stuff$ = basex$ + "\"
  1416.     GOSUB zzFileSelectBoxDD
  1417.     Column = 2
  1418.    ELSE
  1419.     fg = 4: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1420.     dline = 1
  1421.     GOSUB zzFileSelectBoxBB
  1422.     Stuff$ = basex$ + "\" + Directories$(FromDir)
  1423.     GOSUB zzFileSelectBoxDD
  1424.     Column = 4
  1425.    END IF
  1426.  
  1427.   ELSE
  1428.    fg = 4: CALL ziPublishHere(8, 51, "Files", 2, 1): fg = 0
  1429.    fline = 1
  1430.    GOSUB zzFileSelectBoxCC
  1431.    Column = 3
  1432.   END IF
  1433.  
  1434.  
  1435. ' determine what to do, based on keystroke
  1436.  
  1437.   DO
  1438.    stroke$ = "X"
  1439.    DO
  1440.     stroke$ = INKEY$
  1441.    LOOP UNTIL LEN(stroke$) = 0
  1442.    DO
  1443.     stroke$ = INKEY$
  1444.    LOOP WHILE LEN(stroke$) = 0
  1445.    IF LEN(stroke$) = 1 THEN
  1446.     stroke$ = UCASE$(stroke$)
  1447.     SELECT CASE ASC(stroke$)
  1448.     CASE 27   'ESC
  1449.      Pattern$ = "?"
  1450.      RETURN
  1451.     CASE 13   'Enter
  1452.      SELECT CASE Column
  1453.      CASE 1    'enactivate new drive
  1454.       x$ = CHR$(validDevs(dev) + 64) + ":"
  1455.       Pattern$ = x$ + "\" + wild$
  1456.       LINE (112, 88)-(383, 319), 7, BF  'clear the "tree" area
  1457.  
  1458.  
  1459.       GOSUB zzFileSelectBoxII
  1460.       GOTO zzFileSelectBoxProcess
  1461.  
  1462.      CASE 2    'choose new directory
  1463.       IF tree <> levels THEN
  1464.        base$ = ""
  1465.        FOR i = 0 TO tree
  1466.     base$ = base$ + parts$(i)
  1467.     IF MID$(base$, LEN(base$)) <> "\" THEN
  1468.      base$ = base$ + "\"
  1469.     END IF
  1470.        NEXT
  1471.        IF MID$(base$, LEN(base$)) <> "\" THEN
  1472.     base$ = base$ + "\"
  1473.        END IF
  1474.        Pattern$ = base$ + wild$
  1475.        NoDriveSelection = 1
  1476.        GOSUB zzFileSelectBoxII
  1477.        GOTO zzFileSelectBoxProcess
  1478.       END IF
  1479.  
  1480.  
  1481.      CASE 3    'exit with chosen filename
  1482.       Pattern$ = Stuff$
  1483.       RETURN
  1484.  
  1485.      CASE 4    'choose new subdirectory
  1486.       Pattern$ = basex$ + "\" + Directories$(FromDir + dline - 1)
  1487.       Pattern$ = Pattern$ + "\" + wild$
  1488.       NoDriveSelection = 1
  1489.       GOSUB zzFileSelectBoxII
  1490.       GOTO zzFileSelectBoxProcess
  1491.  
  1492.  
  1493.      END SELECT
  1494.  
  1495.     CASE ASC("A") TO ASC("Z")
  1496.      SELECT CASE Column
  1497.      CASE 1
  1498.       i = ASC(stroke$) - 64
  1499.       IF Devices(i) <> 0 THEN
  1500.        dev = Devices(i)
  1501.        GOSUB zzFileSelectBoxAA
  1502.       END IF
  1503.      CASE 3
  1504.       i = FileNames
  1505.       x$ = MID$(FileNames$(i), 1, 1)
  1506.       IF x$ >= stroke$ THEN
  1507.        i = 0
  1508.        DO
  1509.     i = i + 1
  1510.     x$ = MID$(FileNames$(i), 1, 1)
  1511.        LOOP WHILE x$ < stroke$
  1512.       END IF
  1513.       FromFile = i
  1514.       GOSUB zzFileSelectBoxFF
  1515.       fline = 1: GOSUB zzFileSelectBoxCC
  1516.  
  1517.      CASE 4
  1518.       i = Directories
  1519.       x$ = MID$(Directories$(i), 1, 1)
  1520.       IF x$ >= stroke$ THEN
  1521.        i = 0
  1522.        DO
  1523.     i = i + 1
  1524.     x$ = MID$(Directories$(i), 1, 1)
  1525.        LOOP WHILE x$ < stroke$
  1526.       END IF
  1527.       FromDir = i
  1528.       GOSUB zzFileSelectBoxEE
  1529.       dline = 1: GOSUB zzFileSelectBoxBB
  1530.  
  1531.      END SELECT
  1532.     END SELECT
  1533.    ELSE
  1534.     SELECT CASE MID$(stroke$, 2)
  1535.     CASE "I"    'Page UP
  1536.      SELECT CASE Column
  1537.      CASE 3
  1538.       OldFromFile = FromFile
  1539.       IF FromFile + fline > 31 THEN
  1540.        FromFile = FromFile + fline - 31
  1541.       ELSE
  1542.        FromFile = 1
  1543.       END IF
  1544.       IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1545.       fline = 1: GOSUB zzFileSelectBoxCC
  1546.      CASE 4
  1547.       OldFromDir = FromDir
  1548.       IF FromDir + dline > 31 THEN
  1549.        FromDir = FromDir + dline - 31
  1550.       ELSE
  1551.        FromDir = 1
  1552.       END IF
  1553.       IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1554.       dline = 1: GOSUB zzFileSelectBoxBB
  1555.      END SELECT
  1556.     CASE "Q"    'Page DN
  1557.      SELECT CASE Column
  1558.      CASE 3
  1559.       OldFromFile = FromFile
  1560.       IF FromFile + fline + 30 < FileNames THEN
  1561.        FromFile = FromFile + fline + 29
  1562.        IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1563.        fline = 1: GOSUB zzFileSelectBoxCC
  1564.       END IF
  1565.      CASE 4
  1566.       OldFromDir = FromDir
  1567.       IF FromDir + dline + 30 < Directories THEN
  1568.        FromDir = FromDir + dline + 29
  1569.        IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1570.        dline = 1: GOSUB zzFileSelectBoxBB
  1571.       END IF
  1572.      END SELECT
  1573.     CASE "G"    'HOME
  1574.      SELECT CASE Column
  1575.      CASE 3
  1576.       IF FromFile <> 1 THEN
  1577.        FromFile = 1
  1578.        GOSUB zzFileSelectBoxFF
  1579.       END IF
  1580.       fline = 1: GOSUB zzFileSelectBoxCC
  1581.      CASE 4
  1582.       IF FromDir <> 1 THEN
  1583.        FromDir = 1
  1584.        GOSUB zzFileSelectBoxEE
  1585.       END IF
  1586.       dline = 1: GOSUB zzFileSelectBoxBB
  1587.      END SELECT
  1588.     CASE "O"    'END
  1589.      SELECT CASE Column
  1590.      CASE 3
  1591.       OldFromFile = FromFile
  1592.       FromFile = FileNames - 29
  1593.       IF FromFile < 1 THEN
  1594.        FromFile = 1
  1595.       END IF
  1596.       IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1597.       fline = 1: GOSUB zzFileSelectBoxCC
  1598.      CASE 4
  1599.       OldFromDir = FromDir
  1600.       FromDir = Directories - 29
  1601.       IF FromDir < 1 THEN
  1602.        FromDir = 1
  1603.       END IF
  1604.       IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1605.       dline = 1: GOSUB zzFileSelectBoxBB
  1606.      END SELECT
  1607.     CASE "H"    'UP
  1608.      SELECT CASE Column
  1609.      CASE 1     'drives
  1610.       IF dev > 1 THEN
  1611.        dev = dev - 1
  1612.        GOSUB zzFileSelectBoxAA
  1613.       END IF
  1614.      CASE 2     'tree
  1615.       IF tree > 0 THEN
  1616.        tree = tree - 1
  1617.        GOSUB zzFileSelectBoxHH
  1618.       END IF
  1619.      CASE 3     'files
  1620.       i = FromFile + fline - 2
  1621.       IF i > 0 THEN
  1622.        IF fline > 1 THEN
  1623.     fline = fline - 1
  1624.     GOSUB zzFileSelectBoxCC
  1625.        ELSE
  1626.     OldFromFile = FromFile
  1627.     FromFile = FromFile - 30
  1628.     fline = fline + 29
  1629.     IF FromFile < 1 THEN
  1630.      fline = fline + FromFile - 1
  1631.      FromFile = 1
  1632.     END IF
  1633.     IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1634.     GOSUB zzFileSelectBoxCC
  1635.        END IF
  1636.       END IF
  1637.      CASE 4     'subdirs
  1638.       i = FromDir + dline - 2
  1639.       IF i > 0 THEN
  1640.        IF dline > 1 THEN
  1641.     dline = dline - 1
  1642.     GOSUB zzFileSelectBoxBB
  1643.        ELSE
  1644.     OldFromDir = FromDir
  1645.     FromDir = FromDir - 30
  1646.     dline = dline + 29
  1647.     IF FromDir < 1 THEN
  1648.      dline = dline + FromDir - 1
  1649.      FromDir = 1
  1650.     END IF
  1651.     IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1652.     GOSUB zzFileSelectBoxBB
  1653.        END IF
  1654.       END IF
  1655.      END SELECT
  1656.  
  1657.     CASE "P"   'DOWN
  1658.      SELECT CASE Column
  1659.      CASE 1     'drives
  1660.       IF dev < MaxDevs THEN
  1661.        dev = dev + 1
  1662.        GOSUB zzFileSelectBoxAA
  1663.       END IF
  1664.      CASE 2     'tree
  1665.       IF tree < levels THEN
  1666.        tree = tree + 1
  1667.        GOSUB zzFileSelectBoxHH
  1668.       END IF
  1669.      CASE 3     'files
  1670.       i = FromFile + fline
  1671.       IF i <= FileNames THEN
  1672.        IF fline < 30 THEN
  1673.     fline = fline + 1
  1674.     GOSUB zzFileSelectBoxCC
  1675.        ELSE
  1676.     FromFile = i: GOSUB zzFileSelectBoxFF
  1677.     fline = 1: GOSUB zzFileSelectBoxCC
  1678.        END IF
  1679.       END IF
  1680.      CASE 4     'subdirs
  1681.       i = FromDir + dline
  1682.       IF i <= Directories THEN
  1683.        IF dline < 30 THEN
  1684.     dline = dline + 1
  1685.     GOSUB zzFileSelectBoxBB
  1686.        ELSE
  1687.     FromDir = i: GOSUB zzFileSelectBoxEE
  1688.     dline = 1: GOSUB zzFileSelectBoxBB
  1689.        END IF
  1690.       END IF
  1691.      END SELECT
  1692.     CASE "K"   'LEFT
  1693.      SELECT CASE Column
  1694.      CASE 2     'from TREE to DRIVES
  1695.       tree = levels
  1696.       GOSUB zzFileSelectBoxHH
  1697.       fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1698.       fg = 4: CALL ziPublishHere(8, 2, "Drives", 2, 1): fg = 0
  1699.       LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1700.       Column = 1
  1701.      CASE 3     'from FILES to TREE
  1702.       fg = 8: CALL ziPublishHere(8, 51, "Files", 2, 1)
  1703.       fg = 4: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1704.       Column = 2
  1705.      CASE 4     'from SUBDIRS to ?
  1706.       dline = 0: GOSUB zzFileSelectBoxBB
  1707.       fg = 8: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 4
  1708.       IF FileNames = 0 THEN
  1709.        CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1710.        Column = 2
  1711.       ELSE
  1712.        CALL ziPublishHere(8, 51, "Files", 2, 1)
  1713.        Column = 3
  1714.       END IF
  1715.       fg = 0
  1716.      END SELECT
  1717.  
  1718.     CASE "M"   'RIGHT
  1719.      SELECT CASE Column
  1720.      CASE 1     'from DRIVES to TREE
  1721.       dev = Devices(ASC(base$) - 64)
  1722.       GOSUB zzFileSelectBoxAA     'return to original drive
  1723.       fg = 8: CALL ziPublishHere(8, 2, "Drives", 2, 1)
  1724.       fg = 15: LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1725.       fg = 4: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1726.       Column = 2
  1727.      CASE 2     'from TREE to ?
  1728.       tree = levels
  1729.       GOSUB zzFileSelectBoxHH
  1730.       IF FileNames = 0 THEN
  1731.        IF Directories <> 0 THEN
  1732.     fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1733.     fg = 4: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1734.     dline = 1: GOSUB zzFileSelectBoxBB
  1735.     Column = 4
  1736.        END IF
  1737.       ELSE
  1738.        fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1739.        fg = 4: CALL ziPublishHere(8, 51, "Files", 2, 1): fg = 0
  1740.        Column = 3
  1741.       END IF
  1742.      CASE 3     'from FILES to SUBDIRS (if possible)
  1743.       IF Directories <> 0 THEN
  1744.        fg = 8: CALL ziPublishHere(8, 51, "Files", 2, 1)
  1745.        fg = 4: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1746.        dline = 1: GOSUB zzFileSelectBoxBB
  1747.        Column = 4
  1748.       END IF
  1749.      END SELECT
  1750.     END SELECT
  1751.    END IF
  1752.  
  1753.   LOOP
  1754.  
  1755. '   ╔════════════════╗
  1756. '   ║      AA        ╟─────────────────────────────────────────────┐
  1757. '   ╚╤═══════════════╝                                             │
  1758. '    │         change the cursor bar on "dev"                      │
  1759. '    │                                                             │
  1760. '    │         input: dev   output: olddev                         │
  1761. '    └─────────────────────────────────────────────────────────────┘
  1762. zzFileSelectBoxAA:
  1763.  IF dev <> olddev THEN
  1764.   FromRow = 10 + olddev + olddev
  1765.   ToRow = FromRow
  1766.   FromCol = 5
  1767.   ToCol = 10
  1768.   swap1 = bg: swap2 = fg
  1769.   IF olddev > 0 THEN
  1770.    GOSUB zzFileSelectBoxGG
  1771.   END IF
  1772.   FromRow = 10 + dev + dev
  1773.   ToRow = FromRow
  1774.   olddev = dev
  1775.   IF olddev > 0 THEN
  1776.    GOSUB zzFileSelectBoxGG
  1777.   END IF
  1778.  END IF
  1779.  RETURN
  1780.  
  1781.  
  1782.  
  1783. '   ╔════════════════╗
  1784. '   ║      BB        ╟─────────────────────────────────────────────┐
  1785. '   ╚╤═══════════════╝                                             │
  1786. '    │         change the cursor bar on "dline"                    │
  1787. '    │                                                             │
  1788. '    │         input: dline   output: olddline                     │
  1789. '    └─────────────────────────────────────────────────────────────┘
  1790. zzFileSelectBoxBB:
  1791.  IF dline <> olddline THEN
  1792.   FromRow = 10 + olddline
  1793.   ToRow = FromRow
  1794.   FromCol = 67
  1795.   ToCol = 78
  1796.   swap1 = bg: swap2 = fg
  1797.   IF olddline > 0 THEN GOSUB zzFileSelectBoxGG
  1798.   FromRow = 10 + dline
  1799.   ToRow = FromRow
  1800.   olddline = dline
  1801.   IF dline > 0 THEN GOSUB zzFileSelectBoxGG
  1802.  END IF
  1803.  RETURN
  1804.  
  1805.  
  1806.  
  1807. '   ╔════════════════╗
  1808. '   ║      CC        ╟─────────────────────────────────────────────┐
  1809. '   ╚╤═══════════════╝                                             │
  1810. '    │         change the cursor bar on "fline"                    │
  1811. '    │                                                             │
  1812. '    │         input: fline   output: oldfline                     │
  1813. '    └─────────────────────────────────────────────────────────────┘
  1814. zzFileSelectBoxCC:
  1815.  IF fline <> oldfline THEN
  1816.   FromRow = 10 + oldfline
  1817.   ToRow = FromRow
  1818.   FromCol = 51
  1819.   ToCol = 62
  1820.   swap1 = bg: swap2 = fg
  1821.   IF oldfline > 0 THEN
  1822.    GOSUB zzFileSelectBoxGG
  1823.   END IF
  1824.   FromRow = 10 + fline
  1825.   ToRow = FromRow
  1826.   oldfline = fline
  1827.   GOSUB zzFileSelectBoxGG
  1828.   Stuff$ = basex$ + "\" + FileNames$(FromFile + fline - 1)
  1829.   GOSUB zzFileSelectBoxDD
  1830.  END IF
  1831.  RETURN
  1832.  
  1833.  
  1834. '   ╔════════════════╗
  1835. '   ║      DD        ╟─────────────────────────────────────────────┐
  1836. '   ╚╤═══════════════╝                                             │
  1837. '    │     Determine middle of line for publishing "Stuff$"        │
  1838. '    │                                                             │
  1839. '    │                                                             │
  1840. '    └─────────────────────────────────────────────────────────────┘
  1841. zzFileSelectBoxDD:
  1842.  LINE (38, 26)-(601, 46), 3, BF
  1843.  LINE (38, 26)-(601, 46), 8, B
  1844.  CALL ziPublishHere(5, 40 - LEN(Stuff$) \ 2, Stuff$, 1, 2)
  1845.  
  1846.  RETURN
  1847.  
  1848.  
  1849.  
  1850. '   ╔════════════════╗
  1851. '   ║      EE        ╟─────────────────────────────────────────────┐
  1852. '   ╚╤═══════════════╝                                             │
  1853. '    │         Show 30 subdirectories                              │
  1854. '    │                                                             │
  1855. '    │   input: FromDir                                            │
  1856. '    │                                                             │
  1857. '    │                                                             │
  1858. '    └─────────────────────────────────────────────────────────────┘
  1859. zzFileSelectBoxEE:
  1860.  
  1861.  LINE (512, 80)-(Xmax - 11, 319), 7, BF
  1862.  IF FromDir > Directories THEN RETURN
  1863.  IF FromDir > 1 THEN
  1864.   fg = 4: CALL ziPublishHere(11, 65, CHR$(24), 0, 0): fg = 0
  1865.  END IF
  1866.  IF FromDir + 30 <= Directories THEN
  1867.   fg = 4: CALL ziPublishHere(40, 65, CHR$(25), 0, 0): fg = 0
  1868.   j = FromDir + 29
  1869.  ELSE
  1870.   j = Directories
  1871.  END IF
  1872.  
  1873.  FOR i = FromDir TO j
  1874.   k = INSTR(Directories$(i), ".")
  1875.   IF k = 0 THEN
  1876.    x$ = Directories$(i)
  1877.   ELSE
  1878.    x$ = MID$(Directories$(i), 1, k - 1) + SPACE$(8)
  1879.    x$ = MID$(x$, 1, 9) + MID$(Directories$(i), k + 1)
  1880.   END IF
  1881.   CALL ziPublishHere(11 + i - FromDir, 67, x$, 0, 1)
  1882.  NEXT
  1883.  olddline = 0
  1884.  
  1885.  RETURN
  1886.  
  1887.  
  1888. '   ╔════════════════╗
  1889. '   ║      FF        ╟─────────────────────────────────────────────┐
  1890. '   ╚╤═══════════════╝                                             │
  1891. '    │         Show 30 filenames                                   │
  1892. '    │                                                             │
  1893. '    │   input: FromFile                                           │
  1894. '    │                                                             │
  1895. '    │                                                             │
  1896. '    └─────────────────────────────────────────────────────────────┘
  1897. zzFileSelectBoxFF:
  1898.  
  1899.  LINE (384, 80)-(495, 319), 7, BF
  1900.  IF FromFile > FileNames THEN RETURN
  1901.  IF FromFile > 1 THEN
  1902.   fg = 4: CALL ziPublishHere(11, 49, CHR$(24), 0, 0): fg = 0
  1903.  END IF
  1904.  IF FromFile + 30 <= FileNames THEN
  1905.   fg = 4: CALL ziPublishHere(40, 49, CHR$(25), 0, 0): fg = 0
  1906.   j = FromFile + 29
  1907.  ELSE
  1908.   j = FileNames
  1909.  END IF
  1910.  
  1911.  FOR i = FromFile TO j
  1912.   k = INSTR(FileNames$(i), ".")
  1913.   IF k = 0 THEN
  1914.    x$ = FileNames$(i)
  1915.   ELSE
  1916.    x$ = MID$(FileNames$(i), 1, k - 1) + SPACE$(8)
  1917.    x$ = MID$(x$, 1, 9) + MID$(FileNames$(i), k + 1)
  1918.   END IF
  1919.   CALL ziPublishHere(11 + i - FromFile, 51, x$, 0, 0)
  1920.  NEXT
  1921.  oldfline = 0
  1922.  
  1923.  RETURN
  1924.  
  1925.  
  1926. '   ╔════════════════╗
  1927. '   ║      GG        ╟─────────────────────────────────────────────┐
  1928. '   ╚╤═══════════════╝                                             │
  1929. '    │         Swap the colours (swap1 and swap2) of a region      │
  1930. '    │                                                             │
  1931. '    │  input: FromCol, FromRow, ToCol, ToRow, swap1, swap2        │
  1932. '    │                                                             │
  1933. '    │                                                             │
  1934. '    └─────────────────────────────────────────────────────────────┘
  1935. zzFileSelectBoxGG:
  1936.  fx = FromCol * 8 - 8
  1937.  fy = FromRow * 8 - 8
  1938.  tx = ToCol * 8 - 1
  1939.  ty = ToRow * 8 - 1
  1940.  FOR ix = fx TO tx
  1941.   FOR iy = fy TO ty
  1942.    SELECT CASE POINT(ix, iy)
  1943.    CASE swap1
  1944.     PSET (ix, iy), swap2
  1945.    CASE swap2
  1946.     PSET (ix, iy), swap1
  1947.    END SELECT
  1948.   NEXT
  1949.  NEXT
  1950.  RETURN
  1951.  
  1952. '   ╔════════════════╗
  1953. '   ║      HH        ╟─────────────────────────────────────────────┐
  1954. '   ╚╤═══════════════╝                                             │
  1955. '    │         change the cursor bar on "tree"                     │
  1956. '    │                                                             │
  1957. '    │         input: tree   output: oldtree                       │
  1958. '    └─────────────────────────────────────────────────────────────┘
  1959. zzFileSelectBoxHH:
  1960.  IF tree <> oldtree THEN
  1961.   FromRow = 12 + oldtree + oldtree
  1962.   ToRow = FromRow
  1963.   FromCol = 15 + oldtree + oldtree
  1964.   ToCol = FromCol + 11
  1965.   swap1 = bg: swap2 = fg
  1966.   IF oldtree <> 255 THEN
  1967.    GOSUB zzFileSelectBoxGG
  1968.   END IF
  1969.   FromRow = 12 + tree + tree
  1970.   ToRow = FromRow
  1971.   FromCol = 15 + tree + tree
  1972.   ToCol = FromCol + 11
  1973.   oldtree = tree
  1974.   GOSUB zzFileSelectBoxGG
  1975.  END IF
  1976.  RETURN
  1977.  
  1978.  
  1979. '   ╔════════════════╗
  1980. '   ║      II        ╟─────────────────────────────────────────────┐
  1981. '   ╚╤═══════════════╝                                             │
  1982. '    │         clear screen areas when changing directory          │
  1983. '    │                                                             │
  1984. '    │                                                             │
  1985. '    └─────────────────────────────────────────────────────────────┘
  1986. zzFileSelectBoxII:
  1987.  oldtree = 255
  1988.  oldfline = 0
  1989.  olddline = 0
  1990.  LINE (112, 16 * tree + 80)-(383, 319), 7, BF
  1991.  LINE (384, 56)-(495, 319), 7, BF
  1992.  LINE (504, 56)-(Xmax - 11, 319), 7, BF
  1993.  Stuff$ = "(Please Wait)"
  1994.  fg = 14: GOSUB zzFileSelectBoxDD: fg = 0
  1995.  RETURN
  1996.  
  1997. END SUB
  1998.  
  1999. '<p>
  2000. '++++++++++++++++++++++++
  2001. SUB zzInPath (Field$)
  2002.  
  2003.   x$ = ".;" + ENVIRON$("PATH")
  2004.   IF RIGHT$(x$, 1) <> ";" THEN x$ = x$ + ";"
  2005.   i = 1
  2006.   DO
  2007.     j = INSTR(i, x$, ";")
  2008.     IF j THEN
  2009.       y$ = UCASE$(MID$(x$, i, j - i))
  2010.       i = j + 1
  2011.       IF RIGHT$(y$, 1) <> "\" THEN y$ = y$ + "\"
  2012.       F$ = y$ + Field$
  2013.       Bad = 0
  2014.       OPEN "I", 1, F$
  2015.       IF Bad = 0 THEN
  2016.     CLOSE 1
  2017.     EXIT DO
  2018.       END IF
  2019.       F$ = ""
  2020.     END IF
  2021.   LOOP WHILE j
  2022.   Bad = 0
  2023.   Field$ = F$
  2024.  
  2025. END SUB
  2026.  
  2027. '<p>
  2028. '++++++++++++++++++++++++
  2029. SUB zzSearchD (Pattern$)
  2030.  
  2031. DIM str AS STRING * 65
  2032.  
  2033.  CALL zzCritOff
  2034.  GOSUB zzSearchDProcess
  2035.  CALL zzCritOn
  2036.  
  2037.  EXIT SUB
  2038.  
  2039. zzSearchDProcess:
  2040.   upperbound = UBOUND(Directories$)
  2041.   str = LTRIM$(RTRIM$(UCASE$(Pattern$)))
  2042.   Pattern$ = "?"
  2043.  
  2044. ' clear the Directories$ array
  2045.  
  2046.  FOR i = 1 TO 500
  2047.   Directories$(i) = ""
  2048.  NEXT
  2049.  Directories = 0
  2050.  
  2051. ' locate the DTA
  2052.  
  2053.  Regs.AX = &H2F00
  2054.  CALL zzBasicInt(&H21)
  2055.  DTAseg = Regs.ES
  2056.  DTAptr = Regs.BX
  2057.  
  2058. ' confirm that the drive (if specified) is valid
  2059.  
  2060.  IF MID$(str, 2, 1) = ":" THEN
  2061.   i = ASC(str)
  2062.   IF i < 65 THEN RETURN
  2063.   IF i > 90 THEN RETURN
  2064.   Regs.AX = &H440E
  2065.   Regs.BX = i - 64
  2066.   CALL zzBasicInt(&H21)
  2067.   IF (Regs.FL AND 256) <> 256 THEN
  2068.    j = Regs.AX AND 255
  2069.    IF (j <> 0) AND (j <> i - 64) THEN
  2070.     i = j + 64
  2071.    END IF
  2072.   END IF
  2073.   Regs.AX = &H1C00
  2074.   Regs.DX = i - 64
  2075.   CALL zzBasicInt(&H21)
  2076.   IF (Regs.AX AND 255) = 255 THEN RETURN
  2077.  END IF
  2078.  
  2079.  x$ = RTRIM$(str)
  2080.  IF (x$ = "") OR (MID$(x$, 2) = ":") THEN
  2081.   x$ = x$ + "*.*"
  2082.  END IF
  2083.  IF (MID$(x$, LEN(x$)) = "\") THEN
  2084.   x$ = x$ + "*.*"
  2085.  END IF
  2086.  
  2087.  IF INSTR(x$, "*") + INSTR(x$, "?") = 0 THEN
  2088.   x$ = x$ + "\*.*"
  2089.  END IF
  2090.  
  2091. ' initiate the search
  2092.  
  2093.  Pattern$ = x$
  2094.  str = x$ + CHR$(0)
  2095.  Regs.AX = &H4E00
  2096.  Regs.CX = &H10
  2097.  Regs.DS = VARSEG(str)
  2098.  Regs.DX = VARPTR(str)
  2099.  CALL zzBasicInt(&H21)
  2100.  
  2101.  DO WHILE (Regs.FL AND 256) = 0
  2102.   DEF SEG = DTAseg
  2103.  
  2104. ' pull the name (letter by letter) from the DTA
  2105.  
  2106.   IF (PEEK(DTAptr + &H15) AND &H10) = &H10 THEN
  2107.    Name$ = ""
  2108.    i = &H1E
  2109.    DO
  2110.     j = PEEK(DTAptr + i)
  2111.     IF j <> 0 THEN
  2112.      Name$ = Name$ + CHR$(j)
  2113.     END IF
  2114.     i = i + 1
  2115.    LOOP UNTIL j = 0
  2116.  
  2117. ' omit "." and ".."
  2118.  
  2119.    IF MID$(Name$, 1, 1) <> "." THEN
  2120.     Directories = Directories + 1
  2121.     IF Directories > upperbound THEN RETURN
  2122.     Directories$(Directories) = Name$
  2123.    END IF
  2124.   END IF
  2125.  
  2126. ' keep going until all matches are found
  2127.  
  2128.   Regs.AX = &H4F00
  2129.   CALL zzBasicInt(&H21)
  2130.  LOOP
  2131.  
  2132. ' now find the first byte of the directory pattern itself
  2133.  
  2134.  IF MID$(str, 2, 1) = ":" THEN
  2135.   start = 3
  2136.  ELSE
  2137.   start = 1
  2138.  END IF
  2139.  DO
  2140.   i = INSTR(start, str, "\")
  2141.   IF i <> 0 THEN
  2142.    start = i + 1
  2143.   END IF
  2144.  LOOP UNTIL i = 0
  2145.  x$ = MID$(str, 1, start - 1)
  2146.  CALL zzValidate(x$)
  2147.  IF MID$(x$, LEN(x$)) <> "\" THEN x$ = x$ + "\"
  2148.  i = INSTR(str, CHR$(0))
  2149.  
  2150.  Pattern$ = RTRIM$(x$ + MID$(str, start, i - start))
  2151.  
  2152.  IF Directories <> 0 THEN
  2153.   SortCount = Directories
  2154.   CALL zzAlphaSort(Directories$())
  2155.  END IF
  2156.  RETURN
  2157. END SUB
  2158.  
  2159. '<p>
  2160. '++++++++++++++++++++++++
  2161. SUB zzSearchF (Pattern$)
  2162.  
  2163. DIM str AS STRING * 65
  2164.  
  2165.  CALL zzCritOff
  2166.  GOSUB zzSearchFProcess
  2167.  CALL zzCritOn
  2168.  
  2169.  EXIT SUB
  2170.  
  2171. zzSearchFProcess:
  2172.  upperbound = UBOUND(FileNames$)
  2173.  str = LTRIM$(RTRIM$(UCASE$(Pattern$)))
  2174.  Pattern$ = "?"
  2175.  
  2176. ' clear the FileNames$ array
  2177.  
  2178.  FOR i = 1 TO 500
  2179.   FileNames$(i) = ""
  2180.  NEXT
  2181.  FileNames = 0
  2182.  
  2183. ' locate the DTA
  2184.  
  2185.  Regs.AX = &H2F00
  2186.  CALL zzBasicInt(&H21)
  2187.  DTAseg = Regs.ES
  2188.  DTAptr = Regs.BX
  2189.  
  2190. ' confirm that the drive (if specified) is valid
  2191.  
  2192.  IF MID$(str, 2, 1) = ":" THEN
  2193.   i = ASC(str)
  2194.   IF i < 65 THEN RETURN
  2195.   IF i > 90 THEN RETURN
  2196.   Regs.AX = &H440E
  2197.   Regs.BX = i - 64
  2198.   CALL zzBasicInt(&H21)
  2199.   IF (Regs.FL AND 256) <> 256 THEN
  2200.    j = Regs.AX AND 255
  2201.    IF (j <> 0) AND (j <> i - 64) THEN
  2202.     i = j + 64
  2203.    END IF
  2204.   END IF
  2205.   Regs.AX = &H1C00
  2206.   Regs.DX = i - 64
  2207.   CALL zzBasicInt(&H21)
  2208.   IF (Regs.AX AND 255) = 255 THEN RETURN
  2209.  END IF
  2210.  
  2211.  x$ = RTRIM$(str)
  2212.  IF (x$ = "") OR (MID$(x$, 2) = ":") THEN
  2213.   x$ = x$ + "*.*"
  2214.  END IF
  2215.  IF (MID$(x$, LEN(x$)) = "\") THEN
  2216.   x$ = x$ + "*.*"
  2217.  END IF
  2218.  
  2219.  IF INSTR(x$, "*") + INSTR(x$, "?") = 0 THEN
  2220.   x$ = x$ + "\*.*"
  2221.  END IF
  2222.  
  2223. ' initiate the search
  2224.  
  2225.  Pattern$ = x$
  2226.  str = x$ + CHR$(0)
  2227.  Regs.AX = &H4E00
  2228.  Regs.CX = &H27
  2229.  Regs.DS = VARSEG(str)
  2230.  Regs.DX = VARPTR(str)
  2231.  CALL zzBasicInt(&H21)
  2232.  
  2233.  DO WHILE (Regs.FL AND 256) = 0
  2234.   DEF SEG = DTAseg
  2235.  
  2236. ' pull the name (letter by letter) from the DTA
  2237.  
  2238.   Name$ = ""
  2239.   i = &H1E
  2240.   DO
  2241.    j = PEEK(DTAptr + i)
  2242.    IF j <> 0 THEN
  2243.     Name$ = Name$ + CHR$(j)
  2244.    END IF
  2245.    i = i + 1
  2246.   LOOP UNTIL j = 0
  2247.  
  2248.   FileNames = FileNames + 1
  2249.   IF FileNames > upperbound THEN RETURN
  2250.   FileNames$(FileNames) = Name$
  2251.  
  2252.   Regs.AX = &H4F00
  2253.   CALL zzBasicInt(&H21)
  2254.  LOOP
  2255.  
  2256.  
  2257. ' now find the first byte of the file pattern itself
  2258.  
  2259.  IF MID$(str, 2, 1) = ":" THEN
  2260.   start = 3
  2261.  ELSE
  2262.   start = 1
  2263.  END IF
  2264.  DO
  2265.   i = INSTR(start, str, "\")
  2266.   IF i <> 0 THEN
  2267.    start = i + 1
  2268.   END IF
  2269.  LOOP UNTIL i = 0
  2270.  x$ = MID$(str, 1, start - 1)
  2271.  CALL zzValidate(x$)
  2272.  IF MID$(x$, LEN(x$)) <> "\" THEN x$ = x$ + "\"
  2273.  i = INSTR(str, CHR$(0))
  2274.  
  2275.  Pattern$ = RTRIM$(x$ + MID$(str, start, i - start))
  2276.  
  2277.  IF FileNames <> 0 THEN
  2278.   SortCount = FileNames
  2279.   CALL zzAlphaSort(FileNames$())
  2280.  END IF
  2281.  RETURN
  2282. END SUB
  2283.  
  2284. '<p>
  2285. '++++++++++++++++++++++++
  2286. SUB zzValidate (Directory$)
  2287.  
  2288. DIM str AS STRING * 65
  2289.  
  2290.  CALL zzCritOff
  2291.  GOSUB zzValidateProcess
  2292.  CALL zzCritOn
  2293.  
  2294.  EXIT SUB
  2295.  
  2296. zzValidateProcess:
  2297.  
  2298.  Candpath$ = LTRIM$(RTRIM$(UCASE$(Directory$)))
  2299.  IF MID$(Candpath$, LEN(Candpath$)) = "\" THEN
  2300.   IF LEN(Candpath$) > 1 THEN
  2301.    IF MID$(Candpath$, 2) <> ":\" THEN
  2302.     Candpath$ = MID$(Candpath$, 1, LEN(Candpath$) - 1)
  2303.    END IF
  2304.   END IF
  2305.  END IF
  2306.  
  2307.  Directory$ = "?"
  2308.  
  2309. ' check that any named drive is valid
  2310.  
  2311.  IF MID$(Candpath$, 2, 1) = ":" THEN
  2312.   i = ASC(MID$(Candpath$, 1, 1))
  2313.   IF i < 65 THEN RETURN
  2314.   IF i > 90 THEN RETURN
  2315.   Regs.AX = &H440E
  2316.   Regs.BX = i - 64
  2317.   CALL zzBasicInt(&H21)
  2318.   IF (Regs.FL AND 256) <> 256 THEN
  2319.    j = Regs.AX AND 255
  2320.    IF (j <> 0) AND (j <> i - 64) THEN
  2321.     i = j + 64
  2322.    END IF
  2323.   END IF
  2324.   Regs.AX = &H1C00
  2325.   Regs.DX = i - 64
  2326.   CALL zzBasicInt(&H21)
  2327.   IF (Regs.AX AND 255) = 255 THEN RETURN
  2328.  END IF
  2329.  
  2330. ' handle special case of root directory
  2331.  
  2332.  IF Candpath$ = "\" THEN
  2333.   Directory$ = ""
  2334.   CALL zzChangeDrive(Directory$)
  2335.   Directory$ = Directory$ + "\"
  2336.   RETURN
  2337.  END IF
  2338.  IF MID$(Candpath$, 2) = ":\" THEN
  2339.   Directory$ = Candpath$
  2340.   RETURN
  2341.  END IF
  2342.  
  2343. ' handle special case of NO directory
  2344.  
  2345.  IF Candpath$ = "" THEN
  2346.   CALL zzChangeDir(Candpath$)
  2347.   Directory$ = Candpath$
  2348.   RETURN
  2349.  END IF
  2350.  IF MID$(Candpath$, 2) = ":" THEN
  2351.   Regs.AX = &H4700
  2352.   Regs.DX = ASC(MID$(Candpath$, 1, 1)) - 64
  2353.   Regs.DS = VARSEG(str)
  2354.   Regs.SI = VARPTR(str)
  2355.   CALL zzBasicInt(&H21)
  2356.   i = INSTR(str, CHR$(0))
  2357.   Directory$ = Candpath$ + "\" + MID$(str, 1, i - 1)
  2358.   RETURN
  2359.  END IF
  2360.  
  2361.  str = Candpath$ + CHR$(0)
  2362.  IF INSTR(str, "*") + INSTR(str, "?") > 0 THEN RETURN
  2363.  
  2364.  
  2365. ' initiate the search
  2366.  
  2367.  Regs.AX = &H4E00
  2368.  Regs.CX = &H10
  2369.  Regs.DS = VARSEG(str)
  2370.  Regs.DX = VARPTR(str)
  2371.  CALL zzBasicInt(&H21)
  2372.  
  2373. ' abandon if not a valid directory
  2374.  
  2375.  IF (Regs.FL AND 256) <> 0 THEN RETURN
  2376. ' locate the DTA
  2377.  
  2378.  Regs.AX = &H2F00
  2379.  CALL zzBasicInt(&H21)
  2380.  DTAseg = Regs.ES
  2381.  DTAptr = Regs.BX
  2382.  
  2383.  DEF SEG = DTAseg
  2384.  attr = PEEK(DTAptr + &H15)
  2385.  IF (attr AND &H10) = 0 THEN RETURN
  2386.  
  2387. ' establish the status quo so that we can change back
  2388.  
  2389.  olddrv$ = ""
  2390.  CALL zzChangeDrive(olddrv$)
  2391.  
  2392.  IF MID$(str, 2, 1) = ":" THEN
  2393.   newdrv$ = MID$(str, 1, 2)
  2394.  ELSE
  2395.   newdrv$ = olddrv$
  2396.  END IF
  2397.  
  2398.  CALL zzChangeDrive(newdrv$)    'change to new drive
  2399.  olddir$ = ""
  2400.  CALL zzChangeDir(olddir$)      'find the current directory on new drive
  2401.  CALL zzChangeDir(str)          'change to the desired directory
  2402.  CALL zzChangeDir(olddir$)      'change back to the current directory
  2403.  CALL zzChangeDrive(olddrv$)    'change back to old drive
  2404.  IF Root = 0 THEN
  2405.   Directory$ = RTRIM$(str)
  2406.  ELSE
  2407.   Directory$ = MID$(str, 1, 2) + "\"
  2408.  END IF
  2409.  RETURN
  2410.  
  2411. END SUB
  2412.  
  2413.